package com.abigdreamer.swing.app.autoupdate;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.activation.DataSource;

public class FileContract {

	/**
	 * 将文件打包成数据块 每块数据格式如下： 0：标识为数据段：AUPD.MARK_DATA_SECT 1-4：数据长度 5-1en：数据
	 * 
	 * @author Darkness
	 * @date 2012-1-2 下午08:27:25
	 * @version V1.0
	 * @param f
	 * @return
	 * @throws IOException
	 */
	public static List<byte[]> packing(File f) throws IOException {

		List<byte[]> datas = new ArrayList<byte[]>();

		FileInputStream fin = new FileInputStream(f);

		byte[] data = new byte[AUPD.DATA_SIZE];// 文件数据缓冲区
		byte[] buffer;// 发送数据缓冲区
		int len = -1;
		while ((len = fin.read(data)) != -1) {
			buffer = new byte[len + 5];
			buffer[0] = AUPD.MARK_DATA_SECT;// 标识为数据段
			Config.copyArray(buffer, Config.getLen(len), 1, 0, 4);// 存放长度

			for (int i = 0; i < len; i++)
				// 组合数据包
				buffer[i + 5] = data[i];

			datas.add(buffer);
		}
		fin.close();

		// 标识为数据段已结束
		datas.add(new byte[] { AUPD.MARK_DATA_END });

		return datas;
	}

	/**
	 * 前五位为头部1位标识+4位长度
	 * 
	 * @author Darkness
	 * @date 2012-1-2 下午08:55:51
	 * @version V1.0
	 * @param data
	 * @return
	 */
	public static List<byte[]> packing(String data) {

		List<byte[]> datas = new ArrayList<byte[]>();

		byte[] dataBytes = data.getBytes();
		int dataPackageSize = (dataBytes.length + AUPD.DATA_SIZE - 1) / AUPD.DATA_SIZE;

		int len = 0;// 当前数据块长度
		for (int i = 1; i <= dataPackageSize; i++) {
			if (i == dataPackageSize) {
				len = dataBytes.length % AUPD.DATA_SIZE;
			} else {
				len = AUPD.DATA_SIZE;
			}
			byte buffer[] = new byte[len + 5];

			buffer[0] = AUPD.MARK_DATA_SECT;// 标识为数据段
			Config.copyArray(buffer, Config.getLen(len), 1, 0, 4);// 4位长度
			// 组合数据包
			int start = (i - 1) * AUPD.DATA_SIZE;
			for (int j = start; j < start + len; j++) {
				buffer[j + 5] = dataBytes[j];
				//System.out.println(j);
			}
				
			datas.add(buffer);
		}

		// 标识为数据段已结束
		datas.add(new byte[] { AUPD.MARK_DATA_END });

		return datas;
	}

	public static byte[] unpacking(InputStream socketIn) throws IOException {
		// 接收数据缓冲区
		byte flagb[] = new byte[1];// 标志
		byte lenb[] = new byte[4];// 长度
		int len = -1;
		boolean isOk = false;
		List<byte[]> datas = new ArrayList<byte[]>();

		Config.print("解包开始...");
		
		// 接收上传的文件数据
		while (true) {
			
			len = socketIn.read(flagb, 0, 1);// 读取标识位
			if (len != 1) {
				Config.print("读取数据标识位失败");
				break;
			}
			
			// 读取数据长度
			if (flagb[0] == AUPD.MARK_DATA_SECT) {
				len = socketIn.read(lenb, 0, 4);
				if (len != 4) {
					Config.print("读取数据头部失败");
					break;
				}
			}
			
			Config.print("读取包"+flagb[0]+", len:"+new String(lenb, 0, 4)+"...");
			
			if (flagb[0] == AUPD.MARK_DATA_SECT) {// 数据内容
				int cLen = Integer.parseInt(new String(lenb, 0, 4));// 数据内容长度
				byte[] data = new byte[cLen];
				len = socketIn.read(data, 0, cLen);
				int totLen = len;
				while (totLen < cLen) {// 不足位要重重读取
					len = socketIn.read(data, totLen, cLen - totLen);
					totLen = totLen + len;
				}
				datas.add(data);
			} else if (flagb[0] == AUPD.MARK_DATA_END) {// 数据结束
				isOk = true;
				break;
			} else {
				Config.print("收到非期望数据," + new String(flagb, 0, 1) + "<<");
				break;
			}
		}// END while

		if (isOk) {
			int totalLength = 0;
			for (byte[] bs : datas) {
				totalLength += bs.length;
			}
			byte[] resultData = new byte[totalLength];

			int offset = 0;
			for (byte[] bs : datas) {
				for (int i = 0; i < bs.length; i++) {
					resultData[offset + i] = bs[i];
				}
				offset += bs.length;
			}
			return resultData;
		}

		return null;
	}
	
	public static byte[] unpacking(List<byte[]> packingData) throws IOException {
		// 接收数据缓冲区
//		byte flagb[] = new byte[1];// 标志
		boolean isOk = false;
		List<byte[]> datas = new ArrayList<byte[]>();

		Config.print("解包开始...");
		
		// 接收上传的文件数据
		for (byte[] bs : packingData) {
			
			// 读取数据长度
			if (bs[0] == AUPD.MARK_DATA_SECT) {
				int cLen = Integer.parseInt(new String(bs, 1, 4));// 数据内容长度
				byte[] data = new byte[cLen];
				Config.copyArray(data, bs, 0, 5, cLen);
				datas.add(data);
			} else if (bs[0] == AUPD.MARK_DATA_END) {// 数据结束
				isOk = true;
				break;
			} else {
				Config.print("收到非期望数据," + new String(bs, 0, 1) + "<<");
				break;
			}
		}// END while

		if (isOk) {
			int totalLength = 0;
			for (byte[] bs : datas) {
				totalLength += bs.length;
			}
			byte[] resultData = new byte[totalLength];

			int offset = 0;
			for (byte[] bs : datas) {
				for (int i = 0; i < bs.length; i++) {
					resultData[offset + i] = bs[i];
				}
				offset += bs.length;
			}
			return resultData;
		}

		return null;
	}

	public static String unpackingCmd(InputStream socketIn) throws IOException {

		// 开始升级处理
		byte flag[] = new byte[1];
		byte cmd[] = new byte[8];// 命令

		// 读取信息
		int len = socketIn.read(flag, 0, 1);
		if (len != 1) {
			Config.print("[C]读取标识位失败");
		}
		if (flag[0] == AUPD.CMD_DATA_SECT) {// 命令行
			len = socketIn.read(cmd, 0, 8);
			if (len != 8) {
				Config.print("读取命令失败");
				return null;
			}
			return Config.parseCmd(cmd);
		} else {
			Config.print("非期望标识位," + flag[0]);
		}

		return null;
	}

	public static void main(String[] args) throws IOException {
		String str = ".\\im\\lib\\ABigDreamer-SwingD-1.0.jar";
		System.out.println(str.length());
		List<byte[]> packData = packing(str);
		byte[] data = unpacking(packData);
		System.out.println(new String(data));
	}
}
